package com.xxxx.seckill.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xxxx.seckill.exception.CountFail;
import com.xxxx.seckill.mapper.GoodsMapper;
import com.xxxx.seckill.mapper.OrderMapper;
import com.xxxx.seckill.pojo.*;
import com.xxxx.seckill.pojo.dto.GoodsDto;
import com.xxxx.seckill.pojo.dto.OrderDto;
import com.xxxx.seckill.service.IGoodsService;
import com.xxxx.seckill.service.IOrderService;
import com.xxxx.seckill.service.ISeckillGoodsService;
import com.xxxx.seckill.service.ISeckillOrderService;
import com.xxxx.seckill.vo.RespBean;
import com.xxxx.seckill.vo.RespBeanEnum;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.Date;
import java.util.Random;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author zhoubin
 * @since 2022-08-20
 */
@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements IOrderService {

    @Autowired
    private ISeckillOrderService iSeckillOrderService;
    @Autowired
    private IGoodsService iGoodsService;
    @Autowired
    private ISeckillGoodsService iSeckillGoodsService;
    @Autowired
    private GoodsMapper goodsMapper;
    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 检查用户是否购买秒杀商品 及商品是否还有库存
     *
     * @param goodsId
     * @param user
     * @return
     */
    @Override
    public FailMessage check(int goodsId, User user) {
        Order order = null;
        SeckillOrder seckillOrder = null;

        // 判断缓存中的 库存
        ValueOperations valueOperations = redisTemplate.opsForValue();

        int firstCount = (int) valueOperations.get("count:" + goodsId);
        valueOperations.set("isCountEmpty:" + goodsId, "false", 6, TimeUnit.HOURS);
        if (firstCount < 1) {
            // 放入一个标识
            valueOperations.set("isCountEmpty:" + goodsId, "0", 6, TimeUnit.HOURS);
            return new FailMessage(false, "库存不足");
        }

        // 缓存中预减库存
        Long count = valueOperations.decrement("count:" + goodsId);
        if (count < 1) {
            valueOperations.increment("count：" + goodsId);
            return new FailMessage(false, "库存不足");
        }
        //获取商品库存数量
        SeckillGoods seckillGoods = iSeckillGoodsService.getOne(
                new LambdaQueryWrapper<SeckillGoods>()
                        .eq(SeckillGoods::getGoodsId, goodsId));
        Integer stockCount = seckillGoods.getStockCount();

        if (stockCount < 1) {
            return new FailMessage(false, "库存不足");
        }

        //从缓存中获取订单
        //判断订单表中该用户是否抢购秒杀商品
        String orderJson = (String) valueOperations.get("order:" + user.getId());
        if (StringUtils.isEmpty(orderJson)) {
            //判断订单表中该用户是否抢购秒杀商品
            LambdaQueryWrapper<Order> lqw2 = new LambdaQueryWrapper<>();
            lqw2.eq(Order::getGoodsId, goodsId).eq(Order::getUserId, user.getId());
            order = this.getOne(lqw2);
        } else {
            order = JSON.parseObject(orderJson, Order.class);
        }

        //判断秒杀表中该用户是否抢购
        String secJson = (String) valueOperations.get("seckillOrder:" + user.getId());
        if (StringUtils.isEmpty(secJson)) {
            //从数据库中查询 秒杀订单
            LambdaQueryWrapper<SeckillOrder> lqw = new LambdaQueryWrapper<>();
            lqw.eq(SeckillOrder::getGoodsId, goodsId).eq(SeckillOrder::getUserId, user.getId());
            seckillOrder = iSeckillOrderService.getOne(lqw);
        } else {
            seckillOrder = JSON.parseObject(secJson, SeckillOrder.class);
        }

        //判断
        if (order != null || seckillOrder != null) {
            return new FailMessage(false, "每人限购1份");
        }
        return new FailMessage(true, "");
    }

    /**
     * 下单
     *
     * @param user
     * @param goodsId
     */
    @Override
    @Transactional
    public Order order(User user, int goodsId) {

        ValueOperations valueOperations = redisTemplate.opsForValue();

        //更新商品表
        boolean update = iSeckillGoodsService.update(new UpdateWrapper<SeckillGoods>()
                .setSql("stock_count = stock_count-1")
                .eq("goods_id", goodsId)
                .gt("stock_count", 0));

        if (!update) {
            throw new CountFail("库存不足");
        }
        //随机生成orderId
        Random r = new Random();
        Integer orderId = r.nextInt(1000);
        if (orderId < 0) {
            orderId = -orderId;
        }
        long lorderId = Long.parseLong(orderId + "");

        //查询商品表
        GoodsDto goods = iGoodsService.getDetail(goodsId);

        //创建订单表
        Order order = new Order(lorderId, user.getId(),
                Long.parseLong(goodsId + ""),
                null, goods.getGoodsName(),
                1, goods.getSeckillPrice(),
                1, 0,
                new Date(), null
        );
        boolean save = this.save(order);
        //保存成功，添加数据进缓存
        if (save) {
            valueOperations.set("order:" + user.getId(), JSON.toJSONString(order), 4, TimeUnit.HOURS);
        }
        //创建秒杀订单表
        SeckillOrder seckillOrder = new SeckillOrder(
                null, user.getId(), lorderId, Long.parseLong(goodsId + ""));
        boolean flag = iSeckillOrderService.save(seckillOrder);
        if (flag) {
            valueOperations.set("seckillOrder:" + user.getId(), JSON.toJSONString(seckillOrder), 4, TimeUnit.HOURS);
        }
        //返回订单表
        Order orderDetail = this.getById(lorderId);
        return orderDetail;

    }

    /**
     * 订单详情
     *
     * @param orderId
     * @return
     */
    @Override
    public RespBean getOrderDetail(String orderId) {
        //传入的参数为空,返回错误信息
        if (orderId == null) {
            return RespBean.error(RespBeanEnum.NO_ORDER);
        }
        //查询的订单为空 ， 返回错误信息
        Order order = this.getById(orderId);
        if (order == null) {
            return RespBean.error(RespBeanEnum.NO_ORDER);
        }

        GoodsDto goodsVo = goodsMapper.getDetail(Integer.parseInt(order.getGoodsId() + ""));
        OrderDto orderDto = new OrderDto(goodsVo, order);
        return RespBean.success(orderDto);
    }

    /**
     * 生成秒杀路径
     *
     * @param user
     * @param goodsId
     * @return
     */
    @Override
    public String createPath(User user, Long goodsId) {
        String path = DigestUtils.md5Hex(UUID.randomUUID().toString() + "114193");
        redisTemplate.opsForValue().set("seckillPath:" + user.getId() + ":" + goodsId, path, 1, TimeUnit.MINUTES);
        return path;
    }

    /**
     * 检查秒杀路径
     *
     * @param user
     * @param goodsId
     * @param path
     * @return
     */
    @Override
    public boolean chechPath(User user, int goodsId, String path) {
        if (StringUtils.isEmpty(path)) {
            return false;
        }
        String redisPath = (String) redisTemplate.opsForValue().get("seckillPath:" + user.getId() + ":" + goodsId);
        if (!path.equals(redisPath)) {
            return false;
        }
        return true;
    }

    /**
     * 检查验证码
     *
     * @param user
     * @param goodsId
     * @param captcha
     * @return
     */
    @Override
    public boolean checkCaptcha(User user, Long goodsId, Integer captcha) {
        String redisCaptcha = (String) redisTemplate.opsForValue().get("captcha:" + user.getId() + ":" + goodsId);
        Integer redisCaptcha2  = Integer.parseInt(redisCaptcha);
        if (redisCaptcha2 == null || captcha == null) {
            return false;
        }
        if (!(redisCaptcha2 == captcha)) {
            return false;
        }
        return true;
    }


}
